/***************************************************************************
 *   Copyright (C) 2007 by netwan   *
 *   root@double_link   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <QApplication>
#include <QWidget>
#include <QMessageBox>
#include <QFileDialog>
#include <QFile>
#include <QTextCodec>
#include <QSettings>
#include <QStandardItemModel>
#include <QHeaderView>

#include <QBuffer>
#include "PubDefine.h"


#include "mainform.h"
#include "nicform.h"
#include "aboutform.h"
#include "hexsprint.h"
#include "core_hander.h"
#include "WorkerThread.h"
#include "ui/dialogfilter.h"
#include "global.h"
extern void getprotoname(u_char proto,char* pname);
extern TWorkerThread* g_thread;
extern u_long iptoul(const ip_address ipaddress);
extern char * iptos(u_long in);
pcap_t * g_adhandle;
int g_NICIndex;
int g_sameRootPacksCount=0;
nodedata* tvw_packet_Tag;

char g_FilterString[255];
int g_packsCount;
int savedpacksCount;
long g_CapBuffer;
int threadCount;
int g_threadCount;
QList<const nodedata*> g_node_lists;
QMap<QString,nodedata *> g_RootNodesHashMap;
QHash<const QStandardItem*,nodedata *> g_ItemValues;

void Tfrmmain::showThreadInfo(const QString &info)
{
	QMessageBox::critical( NULL,"information",
	info,QMessageBox::Ok,QMessageBox::Ok);
		return ;
}
Tfrmmain::Tfrmmain()
{
    ui.setupUi(this);
    

    memHex = new QHexView(ui.splitter_3);
    memHex->setObjectName(QString::fromUtf8("memHex"));
    ui.splitter_3->addWidget(memHex);

    QCoreApplication::setOrganizationName("adm soft");
    QCoreApplication::setOrganizationDomain("wanguangming.com");
    QCoreApplication::setApplicationName("neteye");
    
    QObject::connect(ui.fileExitAction, 
    SIGNAL(triggered()), this, SLOT(fileExit()));
    QObject::connect(ui.snifferSelect_NICAction, 
    SIGNAL(triggered()), this, SLOT(snifferSelectNid()));
    QObject::connect(ui.helpAboutAction, 
    SIGNAL(triggered()), this, SLOT(about()));
    QObject::connect(ui.snifferStartAction, 
    SIGNAL(triggered()), this, SLOT(fileStart()));
    
    QObject::connect(ui.snifferConfigAction,
                     SIGNAL(triggered()),this,SLOT(filterset()));

    QObject::connect(ui.snifferOpenAction,
    SIGNAL(triggered()), this, SLOT(fileOpen()));
    QObject::connect(ui.snifferStopAction, 
    SIGNAL(triggered()), this, SLOT(fileStop()));
    QObject::connect(ui.lvw_root, 
    SIGNAL(clicked(const QModelIndex &)), this, 
    SLOT(lvw_root_itemclicked(const QModelIndex &)));
    
    QObject::connect(ui.lvw_sub,
    SIGNAL(clicked(const QModelIndex &)), this, 
    SLOT(lvw_sub_itemclicked(const QModelIndex &)));
    
    
    QStandardItemModel *model = new QStandardItemModel(0, 6, this);
       

	model->setHeaderData(0, Qt::Horizontal, QApplication::translate("aboutDialog", "#"));
	model->setHeaderData(1, Qt::Horizontal, QApplication::translate("aboutDialog", "开始时间", 0, QApplication::UnicodeUTF8) );
	model->setHeaderData(2, Qt::Horizontal, QApplication::translate("aboutDialog", "客户端(ip:端口)", 0, QApplication::UnicodeUTF8));
	model->setHeaderData(3, Qt::Horizontal, QApplication::translate("aboutDialog", "服务端(ip:端口)", 0, QApplication::UnicodeUTF8));
	model->setHeaderData(4, Qt::Horizontal, QApplication::translate("aboutDialog", "协议", 0, QApplication::UnicodeUTF8));
	model->setHeaderData(5, Qt::Horizontal, QApplication::translate("aboutDialog", "数据包", 0, QApplication::UnicodeUTF8));

	ui.lvw_root->setModel(model);
	ui.lvw_root->setColumnWidth(0,40);
	
	QStandardItemModel *model_subtree = new QStandardItemModel(0, 4, this);
	model_subtree->setHeaderData(0, Qt::Horizontal, QApplication::translate("aboutDialog", "时间偏移", 0, QApplication::UnicodeUTF8));
	model_subtree->setHeaderData(1, Qt::Horizontal, QApplication::translate("aboutDialog", "数据包长度", 0, QApplication::UnicodeUTF8));
	model_subtree->setHeaderData(2, Qt::Horizontal, QApplication::translate("aboutDialog", "数据长度", 0, QApplication::UnicodeUTF8));
	model_subtree->setHeaderData(3, Qt::Horizontal, QApplication::translate("aboutDialog", "数据", 0, QApplication::UnicodeUTF8));
	ui.lvw_sub->setModel(model_subtree);
	QStandardItemModel *model_pkt = new QStandardItemModel(0,1,this);
	ui.tvw_packet->setModel(model_pkt);
	QHeaderView* hv=ui.tvw_packet->header();
	hv->hide();
	

    QSettings settings;
    g_NICIndex=settings.value("ActiveNIC",0).toInt();
    ui.snifferStopAction->setEnabled(false);
}
void Tfrmmain::lvw_root_itemclicked(const QModelIndex &item)
{
	dump(stdout,"start lvw_root_itemclick");
	QStandardItemModel *model = (QStandardItemModel*)ui.lvw_root->model();
	QStandardItemModel *model_sub = (QStandardItemModel*)ui.lvw_sub->model();
	model_sub->removeRows(0,model_sub->rowCount());
	
	QStandardItem* sitem=model->item(item.row());
	nodedata *node =g_ItemValues.value(sitem);
	
	
	dump(stdout,"get treeview item(%d,%d) data: 0x%08x",item.row(),0,node);
	if(node)
	{
		//显示第一个节点
		AddSubNodes(node,true);
		//显示所有子节点
		QList<const nodedata*>::iterator iter;
		for (iter = node->childs.begin();iter!=node->childs.end();++iter)
		{
			nodedata* nd = (nodedata*)*iter;
			AddSubNodes(nd,false);
		}
	}
	dump(stdout,"end lvw_rootSelectItem");	


}
void Tfrmmain::AddSubNodes(nodedata* node,bool isfirstnode)
{
    int srcPkgsize = node->srcpacksize;
	int nodeDataSize = node->datasize;
	if(nodeDataSize <0)
	{
		printf("nodeDataSize:%d", nodeDataSize);
	}
	int offsetData = srcPkgsize - nodeDataSize;
	QStandardItemModel *model = (QStandardItemModel*)ui.lvw_sub->model();
	//QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK")); 
	//QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK")); 
	//QTextCodec * codec=QTextCodec::codecForCStrings(); 
	int itemindex= model->rowCount();
	model->setItem(itemindex,0,new QStandardItem(node->starttime));
	model->setItem(itemindex,1,new QStandardItem(QString::number(srcPkgsize)));
	model->setItem(itemindex,2,new QStandardItem(QString::number(nodeDataSize)));
	
	if(node->proto ==IPPROTO_TCP || node->proto ==IPPROTO_UDP)
	{
		char pdata[2000]="";
		
		
		if(offsetData >0)
		{
			//strcpy(pdata,(const char*)node->srcpackdata + offsetData);
			strncpy(pdata,(char*)node->srcpackdata +offsetData, 1999);	
		}
		
		//QString data=gp_codec->toUnicode(pdata);
		//model->setItem(itemindex,3,new QStandardItem(codec->toUnicode((const char*)pdata)));
		
		model->setItem(itemindex,3,new QStandardItem(QString::fromLocal8Bit(pdata)));	
		
		
		QStandardItem* item = model->item(itemindex);
		g_ItemValues[item] = node;
	}
}
QStandardItem * Tfrmmain::addTreeViewItem(QStandardItemModel *model,QStandardItem* parent,char *fmt, ...)
{
	char buffer[1024];
	va_list ap;
	va_start(ap, fmt);
	vsprintf(buffer, fmt, ap);
	va_end(ap);
	
	QStandardItem *newitem=new QStandardItem();
	newitem->setText(QApplication::translate("aboutDialog",buffer, 0, QApplication::UnicodeUTF8));
	if(parent)
	{
		parent->setChild(parent->rowCount(),0,newitem);
	}
	else
	{
		model->setItem(model->rowCount(),0,newitem);	
	}
	return newitem;
	
}
void Tfrmmain::lvw_sub_itemclicked(const QModelIndex &item)
{

QStandardItemModel *model = (QStandardItemModel*)ui.tvw_packet->model();

QStandardItemModel *model_sub = (QStandardItemModel*)ui.lvw_sub->model();
QStandardItem* sitem = model_sub->item(item.row());
nodedata *node =g_ItemValues.value(sitem);
if(!node)
	return;
dump(stdout,"start lvw_sub_itemclicked");
int itemindex = item.row();
int ip_len=0;

ether_header *eh=NULL;
ip_header *ih=NULL;
udp_header *uh=NULL;
tcp_header *th=NULL;
pppoe_header *ph=NULL;

if(node)
{
  model->removeRows(0,model->rowCount());
  
  tvw_packet_Tag = node;
  eh =(ether_header *)node->srcpackdata;

  QStandardItem* pppoeid=NULL;
  QStandardItem* ipid=NULL;
  QStandardItem* udpid=NULL;
  QStandardItem* tcpid=NULL;
  QStandardItem* tcpflagid=NULL;

  QStandardItem *pid=addTreeViewItem(model,NULL,"数据包: %d字节",node->srcpacksize);

  int packet_header_len = ETHER_HDRLEN + (node->ip_flag ? node->ip_header_len:0) +
  (node->udp_flag ? node->udp_header_len:0) + (node->tcp_flag ? node->tcp_header_len:0);
	  SetNodeTagData(pid,0,0,0,packet_header_len);
  
  QStandardItem *eid=addTreeViewItem(model,pid,"Ethernet 头部");
  
  SetNodeTagData(eid,1,1,0,ETHER_HDRLEN);

  //QStandardItem* eid0=ui.tvw_packet->Items->AddChild(eid,dstmacaddr);
  
  QStandardItem *eid0=addTreeViewItem(model,eid,"目标Mac地址: %02x.%02x.%02x.%02x.%02x.%02x",eh->ether_dhost[0],eh->ether_dhost[1],eh->ether_dhost[2],eh->ether_dhost[3],eh->ether_dhost[4],eh->ether_dhost[5]);
  
  SetNodeTagData(eid0,2,2,0,6);//第0位开始6个字节

  QStandardItem *eid1=addTreeViewItem(model,eid,"来源Mac地址: %02x.%02x.%02x.%02x.%02x.%02x",eh->ether_shost[0],eh->ether_shost[1],eh->ether_shost[2],eh->ether_shost[3],eh->ether_shost[4],eh->ether_shost[5]);
  SetNodeTagData(eid1,2,2,6,6);//第6位开始6个字节

  //QStandardItem* eid2=ui.tvw_packet->Items->AddChild(eid,stype);

  QStandardItem *eid2=addTreeViewItem(model,eid,"类型:%d",ntohs(eh->ether_type));
  
  SetNodeTagData(eid2,2,2,12,2);//第6位开始2个字节

  if (node->pppoe_flag)
  {
	ph = (pppoe_header*)((u_char*)eh+14);
	//pppoeid =ui.tvw_packet->Items->AddChild(pid, "PPPOE 头部");
    QStandardItem *pppoeid=addTreeViewItem(model,pid,"PPPOE 头部");
	SetNodeTagData(pppoeid,1,1,0,PPPOE_HDRLEN);
	//QStandardItem* pppoeid0 = tvw_packet->Items->AddChild( pppoeid,Format("版本:%d",ARRAYOFCONST((ph->ver_type>>4))));
	
  	QStandardItem *pppoeid0=addTreeViewItem(model,pppoeid,"版本:%d",ph->ver_type>>4);
  
	SetNodeTagData(pppoeid0,2,2,0,1);//第0位开始1个字节
	//QStandardItem* pppoeid1 = tvw_packet->Items->AddChild( pppoeid,Format("类型:%d",ARRAYOFCONST((ph->ver_type & 0x0f))));
	
	QStandardItem *pppoeid1=addTreeViewItem(model,pppoeid,"类型:%d",ph->ver_type & 0x0f);
	
  	
	SetNodeTagData(pppoeid1,2,2,1,1);//第1位开始1个字节
	//QStandardItem* pppoeid2 = tvw_packet->Items->AddChild( pppoeid,Format("SessionID:%d",ARRAYOFCONST((ntohs(ph->session_id)))));
	QStandardItem *pppoeid2=addTreeViewItem(model,pppoeid,"SessionID:%d",ntohs(ph->session_id));

	SetNodeTagData(pppoeid2,2,2,2,2);//第2位开始2个字节
	//QStandardItem* pppoeid3 = tvw_packet->Items->AddChild( pppoeid,Format("长度:%d",ARRAYOFCONST((ntohs(ph->length)))));
	QStandardItem *pppoeid3=addTreeViewItem(model,pppoeid,"长度:%d",ntohs(ph->length));
  	
	SetNodeTagData(pppoeid3,2,2,4,2);//第4位开始2个字节
  }
  int ip_offset=0;
  if (node->ip_flag)
  {
	  ip_offset = ETHER_HDRLEN + (node->pppoe_flag ? 8:0);
	  ih = (ip_header *) ((u_char*)eh +
		 ip_offset); //length of ethernet header  14
	  ip_len = (ih->ver_ihl & 0xf) * 4;

	  //ipid = ui.tvw_packet->Items->AddChild(pid,"IP 头部");
	  ipid=addTreeViewItem(model,pid,"IP 头部");
  
	  SetNodeTagData(ipid,1,1,ip_offset+0,ip_len);
	  //QStandardItem* ipid0 = tvw_packet->Items->AddChild( ipid,Format("头部长度:%d",ARRAYOFCONST((ih->ver_ihl & 0x0f))));
	  QStandardItem *ipid0=addTreeViewItem(model,ipid,"头部长度:%d",ih->ver_ihl & 0x0f);

	  
	  SetNodeTagData(ipid0,2,2,ip_offset+0,1);//第0位开始1个字节
	  //QStandardItem* ipid1 = tvw_packet->Items->AddChild( ipid,Format("版本:%d",ARRAYOFCONST((ih->ver_ihl >> 4))));
	  QStandardItem *ipid1=addTreeViewItem(model,ipid,"版本:%d",ih->ver_ihl >> 4);
	  
	  SetNodeTagData(ipid1,2,2,ip_offset+0,1);//第0位开始1个字节
	  //QStandardItem* ipid2 = tvw_packet->Items->AddChild( ipid,Format("服务类型:%d",ARRAYOFCONST((ih->tos))));
	  QStandardItem *ipid2=addTreeViewItem(model,ipid,"服务类型:%d",ih->tos);
	  
	  SetNodeTagData(ipid2,2,2,ip_offset+1,1);//第1位开始1个字节
	  //QStandardItem* ipid3 = tvw_packet->Items->AddChild( ipid,Format("总长度:%d",ARRAYOFCONST((ntohs(ih->tlen)))));
	  QStandardItem *ipid3=addTreeViewItem(model,ipid,"总长度:%d",ntohs(ih->tlen));
	  
	  
	  SetNodeTagData(ipid3,2,2,ip_offset+2,2);//第2位开始2个字节
	  //QStandardItem* ipid4 = tvw_packet->Items->AddChild( ipid,Format("标识符:%d",ARRAYOFCONST((ntohs(ih->identification)))));
	  QStandardItem *ipid4=addTreeViewItem(model,ipid,"标识符:%d",ntohs(ih->identification));
	  
	  
	  SetNodeTagData(ipid4,2,2,ip_offset+4,2);//第4位开始2个字节
	  //QStandardItem* ipid5 = tvw_packet->Items->AddChild( ipid,Format("偏移:%d",ARRAYOFCONST((ih->flags_fo & 0x1fff))));
	  QStandardItem *ipid5=addTreeViewItem(model,ipid,"偏移:%d",ih->flags_fo & 0x1fff);

	  
	  SetNodeTagData(ipid5,2,2,ip_offset+6,2);//第6位开始2个字节
	  //QStandardItem* ipid6 = tvw_packet->Items->AddChild( ipid,Format("TTL:%d",ARRAYOFCONST((ih->ttl))));
	  QStandardItem *ipid6=addTreeViewItem(model,ipid,"TTL:%d",ih->ttl);
	  
	  SetNodeTagData(ipid6,2,2,ip_offset+8,1);//第8位开始1个字节
	  //QStandardItem* ipid7 = tvw_packet->Items->AddChild( ipid,Format("协议:%d",ARRAYOFCONST((ih->proto))));
	  QStandardItem *ipid7=addTreeViewItem(model,ipid,"协议:%d",ih->proto);
	  
	  SetNodeTagData(ipid7,2,2,ip_offset+9,1);//第9位开始1个字节
	  //QStandardItem* ipid8 = tvw_packet->Items->AddChild( ipid,Format("校验值:%d",ARRAYOFCONST((ntohs(ih->crc)))));
	  QStandardItem *ipid8=addTreeViewItem(model,ipid,"校验值:%d",ntohs(ih->crc));
	  
	  SetNodeTagData(ipid8,2,2,ip_offset+10,2);//第10位开始2个字节
	  //QStandardItem* ipid9 = tvw_packet->Items->AddChild( ipid,Format("源IP:%d.%d.%d.%d",ARRAYOFCONST((ih->saddr.byte1,ih->saddr.byte2,ih->saddr.byte3,ih->saddr.byte4))));
	  QStandardItem *ipid9=addTreeViewItem(model,ipid,"源IP:%d.%d.%d.%d",ih->saddr.byte1,ih->saddr.byte2,ih->saddr.byte3,ih->saddr.byte4);
	  
	  SetNodeTagData(ipid9,2,2,ip_offset+12,4);//第12位开始4个字节
	  //QStandardItem* ipid10 = tvw_packet->Items->AddChild( ipid,Format("目标IP:%d.%d.%d.%d",ARRAYOFCONST((ih->daddr.byte1,ih->daddr.byte2,ih->daddr.byte3,ih->daddr.byte4))));
	  QStandardItem *ipid10=addTreeViewItem(model,ipid,"目标IP:%d.%d.%d.%d",ih->daddr.byte1,ih->daddr.byte2,ih->daddr.byte3,ih->daddr.byte4);
	  
	  SetNodeTagData(ipid10,2,2,ip_offset+16,4);//第16位开始4个字节
  }
  if (node->udp_flag)
  {
	  int udpoffset = ip_offset + ip_len;
	  uh = (udp_header *) ((u_char*)ih + ip_len);
	  udpid =addTreeViewItem(model,pid,"UDP 头部");
	  SetNodeTagData(udpid,1,1,udpoffset+0,8);
	  //QStandardItem* udpid0 = ui.tvw_packet->Items->AddChild( udpid,Format("源端口:%d",ARRAYOFCONST((ntohs(uh->sport)))));
	  QStandardItem *udpid0=addTreeViewItem(model,udpid,"头部长度:%d",ih->ver_ihl & 0x0f);
	  
	  SetNodeTagData(udpid0,2,2,udpoffset+0,2);//第0位开始2个字节
	  //QStandardItem* udpid1 = ui.tvw_packet->Items->AddChild( udpid,Format("目标端口:%d",ARRAYOFCONST((ntohs(uh->dport)))));
	  QStandardItem *udpid1=addTreeViewItem(model,udpid,"目标端口:%d",ntohs(uh->dport));
	  SetNodeTagData(udpid1,2,2,udpoffset+2,2);
	  //QStandardItem* udpid2 = ui.tvw_packet->Items->AddChild( udpid,Format("长度:%d",ARRAYOFCONST((ntohs(uh->len)))));
	  QStandardItem *udpid2=addTreeViewItem(model,udpid,"长度:%d",ntohs(uh->len));
	  SetNodeTagData(udpid2,2,2,udpoffset+4,2);
	  //QStandardItem* udpid3 = ui.tvw_packet->Items->AddChild( udpid,Format("校验值:%d",ARRAYOFCONST((ntohs(uh->crc)))));
	  QStandardItem *udpid3=addTreeViewItem(model,udpid,"校验值:%d",ntohs(uh->crc));
	  SetNodeTagData(udpid3,2,2,udpoffset+6,2);
  }
  if (node->tcp_flag)
  {
	  int tcpoffset = ip_offset + ip_len;
	  th = (tcp_header*)((u_char*)ih + ip_len);
	  tcpid = addTreeViewItem(model,pid,"TCP 头部");
	  SetNodeTagData(tcpid,1,1,tcpoffset+0,20);
	  //QStandardItem* tcpid0 = ui.tvw_packet->Items->AddChild( tcpid,Format("源端口:%d",ARRAYOFCONST((ntohs(th->sport)))));
	  QStandardItem *tcpid0=addTreeViewItem(model,tcpid,"源端口:%d",ntohs(th->sport));
	  SetNodeTagData(tcpid0,2,2,tcpoffset+0,2);
	  //QStandardItem* tcpid1 = ui.tvw_packet->Items->AddChild( tcpid,Format("目标端口:%d",ARRAYOFCONST((ntohs(th->dport)))));
	  QStandardItem *tcpid1=addTreeViewItem(model,tcpid,"目标端口:%d",ntohs(th->dport));
	  SetNodeTagData(tcpid1,2,2,tcpoffset+2,2);
	  //QStandardItem* tcpid2 = ui.tvw_packet->Items->AddChild( tcpid,Format("队列:%u",ARRAYOFCONST((ntohl(th->th_seq)))));
	  QStandardItem *tcpid2=addTreeViewItem(model,tcpid,"队列:%u",ntohl(th->th_seq));
	  SetNodeTagData(tcpid2,2,2,tcpoffset+4,4);
	  //QStandardItem* tcpid3 = ui.tvw_packet->Items->AddChild( tcpid,Format("认可:%u",ARRAYOFCONST((ntohl(th->th_ack)))));
	  QStandardItem *tcpid3=addTreeViewItem(model,tcpid,"认可:%u",ntohl(th->th_ack));
	  SetNodeTagData(tcpid3,2,2,tcpoffset+8,4);
	  //QStandardItem* tcpid4 = ui.tvw_packet->Items->AddChild( tcpid,Format("头部长度:%d",ARRAYOFCONST((th->th_lenres >>4))));
	  QStandardItem *tcpid4=addTreeViewItem(model,tcpid,"头部长度:%d",th->th_lenres >>4);
	  SetNodeTagData(tcpid4,2,2,tcpoffset+12,1);

	  //QStandardItem *tcpflagid = ui.tvw_packet->Items->AddChild( tcpid,Format("标记:0x%02x",ARRAYOFCONST((th->th_flag & 0x3f))));
	  tcpflagid=addTreeViewItem(model,tcpid,"标记:0x%02x",th->th_flag & 0x3f);
	  SetNodeTagData(tcpflagid,2,2,tcpoffset+13,1);

	  //QStandardItem* nodeflag1 = ui.tvw_packet->Items->AddChild( tcpflagid,Format("FIN:%d",ARRAYOFCONST((th->th_flag & 0x01 ? 1:0))));
	  QStandardItem *nodeflag1=addTreeViewItem(model,tcpflagid,"FIN:%d",th->th_flag & 0x01 ? 1:0);
	  int ImageIndex;
	  ImageIndex = th->th_flag & 0x01 ? 4 : 3;
	  SetNodeTagData(nodeflag1,ImageIndex,ImageIndex,tcpoffset+13,1);
	  //QStandardItem* nodeflag2 = ui.tvw_packet->Items->AddChild( tcpflagid,Format("SYN:%d",ARRAYOFCONST((th->th_flag & 0x02 ? 1:0))));
	  QStandardItem *nodeflag2=addTreeViewItem(model,tcpflagid,"SYN:%d",th->th_flag & 0x02 ? 1:0);
	  ImageIndex =  th->th_flag & 0x02 ? 4 : 3;
	  SetNodeTagData(nodeflag2,ImageIndex,ImageIndex,tcpoffset+13,1);
	  //QStandardItem* nodeflag3 = ui.tvw_packet->Items->AddChild( tcpflagid,Format("RST:%d",ARRAYOFCONST((th->th_flag & 0x04 ? 1:0))));
	  QStandardItem *nodeflag3=addTreeViewItem(model,tcpflagid,"RST:%d",th->th_flag & 0x04 ? 1:0);
	  ImageIndex =  th->th_flag & 0x04 ? 4 : 3;
	  SetNodeTagData(nodeflag3,ImageIndex,ImageIndex,tcpoffset+13,1);
	  //QStandardItem* nodeflag4 = ui.tvw_packet->Items->AddChild( tcpflagid,Format("PSH:%d",ARRAYOFCONST((th->th_flag & 0x08 ? 1:0))));
	  QStandardItem *nodeflag4=addTreeViewItem(model,tcpflagid,"PSH:%d",th->th_flag & 0x08 ? 1:0);
	  ImageIndex =  th->th_flag & 0x08 ? 4 : 3;
	  SetNodeTagData(nodeflag4,ImageIndex,ImageIndex,tcpoffset+13,1);
	  //QStandardItem* nodeflag5 = ui.tvw_packet->Items->AddChild( tcpflagid,Format("ACK:%d",ARRAYOFCONST((th->th_flag & 0x10 ? 1:0))));
	  QStandardItem *nodeflag5=addTreeViewItem(model,tcpflagid,"ACK:%d",th->th_flag & 0x10 ? 1:0);
	  ImageIndex =  th->th_flag & 0x10 ? 4 : 3;
	  SetNodeTagData(nodeflag5,ImageIndex,ImageIndex,tcpoffset+13,1);
	  //QStandardItem* nodeflag6 = ui.tvw_packet->Items->AddChild( tcpflagid,Format("URG:%d",ARRAYOFCONST((th->th_flag & 0x20 ? 1:0))));
	  QStandardItem *nodeflag6=addTreeViewItem(model,tcpflagid,"URG:%d",th->th_flag & 0x20 ? 1:0);
	  ImageIndex =  th->th_flag & 0x20 ? 4 : 3;
	  SetNodeTagData(nodeflag6,ImageIndex,ImageIndex,tcpoffset+13,1);

	  //QStandardItem* tcpid5 = ui.tvw_packet->Items->AddChild( tcpid,Format("窗口:%u",ARRAYOFCONST((ntohs(th->th_win)))));
	  QStandardItem *tcpid5=addTreeViewItem(model,tcpid,"窗口:%u",ntohs(th->th_win));
	  SetNodeTagData(tcpid5,2,2,tcpoffset+14,2);

	  //QStandardItem* tcpid6 = ui.tvw_packet->Items->AddChild( tcpid,Format("校验值:%u",ARRAYOFCONST((ntohs(th->th_sum)))));
	  QStandardItem *tcpid6=addTreeViewItem(model,tcpid,"校验值:%u",ntohs(th->th_sum));
	  SetNodeTagData(tcpid6,2,2,tcpoffset+16,2);
	  //QStandardItem* tcpid7 = ui.tvw_packet->Items->AddChild( tcpid,Format("关键点:%u",ARRAYOFCONST((ntohs(th->th_urp)))));
	  QStandardItem *tcpid7=addTreeViewItem(model,tcpid,"关键点:%u",ntohs(th->th_urp));
	  SetNodeTagData(tcpid7,2,2,tcpoffset+18,2);
  }
  

  if (pid) ui.tvw_packet->expand(pid->index());
  if (eid) ui.tvw_packet->expand(eid->index());
  if (pppoeid) ui.tvw_packet->expand(pppoeid->index());
  if (ipid) ui.tvw_packet->expand(ipid->index());
  if (udpid) ui.tvw_packet->expand(udpid->index());
  if (tcpid) ui.tvw_packet->expand(tcpid->index());
  if (tcpflagid) ui.tvw_packet->expand(tcpflagid->index());
  //pid->MakeVisible();
 // WxTreeCtrl1->EnsureVisible(pid);
 // char hex[MAXCAPMESSAGE+1]="";
 // char lbl[MAXCAPMESSAGE+1]="";
 // char asc[MAXCAPMESSAGE+1]="";
 // hex_and_ascii_print("\r\n",(const u_char*)node->srcpackdata,node->srcpacksize,lbl,hex,asc);
  //memLbl->Text =lbl;
  //memHex->Text =hex;
  //memAsc->Text =asc;

  char pdata[16384]="";
  if(node->srcpacksize >0 && 
  node->srcpacksize < 2000 &&  
  node->datasize>0 )
  {
  	int data_offset = node->srcpacksize - node->datasize;
  	strncpy(pdata,
  (char*)((u_char*)node->srcpackdata + data_offset), node->datasize >1500 ? 1500:node->datasize);
  }
  //memHex->setData(&pdata);
  //reTxtData->Text = pdata;
  stream.clear();
  int i_count = node->datasize >1500 ? 1500:node->datasize;
  for(int i=0;i<i_count ;i++)
  {
  	stream.push_back(pdata[i]);
  }
  //QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK")); 
  //QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK")); 
  //memHex->setData(&stream);
  QBuffer *buffer = new QBuffer(&stream);
  buffer->open(QIODevice::ReadWrite);
  QDataStream out(buffer);
  out << QApplication::palette();
  memHex->clear();
  memHex->setData(QSharedPointer<QIODevice>(buffer));
  QString infoAsc(QString::fromLocal8Bit(pdata));
  ui.memAsc->setText(infoAsc);
  //ui.tvw_packet->Items->EndUpdate();
}
dump(stdout,"end lvw_subSelectItem");
}
void Tfrmmain::SetNodeTagData(QStandardItem* item,int imageindex,int selectedindex,int start,int count)
{
   //node->ImageIndex=imageindex;
   //node->SelectedIndex=selectedindex;
   //node->Data = (void*)((start << 8) + count);//第start位开始count个字节;
}
void Tfrmmain::fileStart()//开始抓包 
{
     int ret = QMessageBox::warning(this, tr("My Application"),
                   tr("The document has been modified.\n"
                      "Do you want to save your changes?"),
                   QMessageBox::Save | QMessageBox::Discard
                   | QMessageBox::Cancel,
                   QMessageBox::Save);
     g_thread = new TWorkerThread();

     if (!g_thread)
	 {
	               QMessageBox::critical(this, tr("My App"),
                          tr("Can not start workerthread."),
                          QMessageBox::Close); 
			return;
	}

	QObject::connect(g_thread, 
    SIGNAL(ShowError(const QString&)), this, SLOT(showThreadInfo(const QString&)));
    
	QObject::connect(g_thread,
	SIGNAL(OnStartCat()),this,SLOT(OnstartCat()));

	QObject::connect(g_thread, 
    SIGNAL(terminated()), this, SLOT(OnendCat()));
	QObject::connect(g_thread, 
    SIGNAL(finished()), this, SLOT(OnendCat()));
    
    QObject::connect(g_thread, 
    SIGNAL(OpenDevice()), this, SLOT(OnOpenDevice()));
    
    QObject::connect(g_thread,
    SIGNAL(CatchPACKET(nodedata*)),this,SLOT(OnCatchPACKET(nodedata*)));
    g_thread->start();
}
void Tfrmmain::filterset()
{
    DialogFilter *dl= new DialogFilter();
    dl->show();
}

void Tfrmmain::fileOpen()
{
	if(g_thread  && g_node_lists.size() > savedpacksCount)
	{
		int ianser = QMessageBox::question(this,"提示","正在捕捉,你要停止吗?",QMessageBox::Yes|QMessageBox::No);
		//int ianser = MessageBox(this->Handle,"正在捕捉,你要停止吗?","提示",MB_YESNO|MB_ICONWARNING);
		switch (ianser) {
		case QMessageBox::Yes:
		fileStop();
		break;
		case QMessageBox::No:
		return;
		default:
			;
		}
	}
	if(!dataSaved && g_node_lists.size() > savedpacksCount)
	{
	   int ianser = QMessageBox::question(this,"提示",
	   "若不保存,当前已捕捉的数据包将丢弃.\n注意:如果保存到文件,以后还可以再打开.\n\n你希望保存这些数据吗?",QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel);
	   switch(ianser) {
	   case QMessageBox::No:
	   break;
	   case QMessageBox::Yes:
	   fileSave();
	   break;
	   case QMessageBox::Cancel:
	   return;
	   break;
	   default:
		   ;
	   }
	}
	QFileDialog* OpenDialog1 = new QFileDialog();
	OpenDialog1->setAcceptMode(QFileDialog::AcceptOpen);
	OpenDialog1->setFilter(tr("Packet Captch File (*.cap)"));
	//bool isucess=OpenDialog1->exec();
	QString filename = OpenDialog1->getOpenFileName(this,tr("open file"),
	"",tr("Packet Captch File (*.cap)"));
	if(QFile::exists(filename))
	{
		ClearCapData();
		//

		QMessageBox::information(this,"info",filename);
		pcap_t *fp;
		char errbuf[PCAP_ERRBUF_SIZE];
		
		dump(stdout,"Open file %s",qPrintable(filename));
		/* Open the capture file */
		if ((fp = pcap_open_offline(qPrintable(filename),			// name of the device
							 errbuf					// error buffer
							 )) == NULL)
		{
			dump(stdout,"\nUnable to open the file %s.\n", filename.toAscii());
			return ;
		}
	
		/* read and dispatch packets until EOF is reached */

		//pcap_loop(fp, 0, dispatcher_handler, NULL);
	
		pcap_close(fp);
		
		QMap<QString,nodedata *>::iterator iter;
		for (iter = g_RootNodesHashMap.begin();iter!=g_RootNodesHashMap.end();++iter)
		{
			nodedata* newnode = iter.value();
			OnCatchPACKET(newnode);
		}
		return ;
}
}
void Tfrmmain::fileSave()
{
	
}
void Tfrmmain::ClearCapData()
{
   ui.lvw_root->model()->removeRows(0,ui.lvw_root->model()->rowCount());
   ui.lvw_sub->model()->removeRows(0,ui.lvw_sub->model()->rowCount());
   g_RootNodesHashMap.clear();
   g_node_lists.clear();
   dataSaved = true;	
}

void Tfrmmain::fileStop()
{
	if(g_thread)
	{
        g_thread->StopCap();
		//this->c_Thread->Terminate();
	}
}
void Tfrmmain::fileExit()
{   
    dump(stdout, "Application is Existing..." );
    QApplication::exit();
}   
void Tfrmmain::about()
{
    TaboutForm * frm = new TaboutForm();
    frm->setWindowModality(Qt::WindowModal);
    frm->show();
}
void Tfrmmain::snifferSelectNid()
{
    TNicDialog1 *dl= new TNicDialog1();
    QObject::connect(dl, 
    SIGNAL(ShowError(const QString&)), this, SLOT(showThreadInfo(const QString&)));

    dl->show();
}
void Tfrmmain::closeEvent(QCloseEvent * event)
{
    dump(stdout, "Application is Existing..." );
    QApplication::exit();
}

void Tfrmmain::OnstartCat()
{
	dump(stdout,"OnStartCat()");
	ui.fileNewAction->setEnabled(false);
    ui.snifferStopAction->setEnabled (true);
	ui.snifferStartAction->setEnabled ( false);
	ui.snifferSelect_NICAction->setEnabled (false);
	ui.snifferConfigAction->setEnabled( false);
	dataSaved = false;
}
void Tfrmmain::OnendCat()
{
	dump(stdout,"OnendCat()");	
	ui.fileNewAction->setEnabled(true);
	ui.snifferStopAction->setEnabled(false);
	ui.snifferStartAction->setEnabled ( true);
	ui.snifferSelect_NICAction->setEnabled (true);
	ui.snifferConfigAction->setEnabled( true);
	g_thread = NULL;
}
void Tfrmmain::OnOpenDevice()
{
	pcap_if_t *alldevs;
	pcap_if_t *d;
	int inum=0;
	int i=0;

	char errbuf[PCAP_ERRBUF_SIZE];
    
    /* Retrieve the device list on the local machine */
    if (pcap_findalldevs(&alldevs, errbuf) == -1)
    {
		dump(stdout,"Error in pcap_findalldevs: %s\n", errbuf);
		return;
	}

    for(d=alldevs; d; d=d->next)
	++i;
	dump(stdout,"found %d cards",i);
	if(i==0)
	{
		showThreadInfo("\n网卡初始化错误!请确认是否正确的安装了WinPcap.\n");
		return ;
	}

	inum = g_NICIndex;
	dump(stdout,"last open device num is:%d",inum);
	if(inum < 1 || inum > i)
	{
		dump(stdout,"\nInterface number out of range.\n");
		/* Free the device list */
        pcap_freealldevs(alldevs);
		return ;
    }

    /* Jump to the selected adapter */
	for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++)
	dump(stdout,"%d:Skipping device %s",i,d->name);
	/* Open the device */
   dump(stdout,"%d:Opening device %s",i,d->name);
   try
   {
   g_adhandle= pcap_open_live(d->name,	// name of the device
							 65536,			// portion of the packet to capture. 
											// 65536 grants that the whole packet will be captured on all the MACs.
							 1,				// promiscuous mode (nonzero means promiscuous)
							 1000,			// read timeout
							 errbuf			// error buffer
							 );
   }
   catch(...)
   {;}
  	
   if (g_adhandle == NULL)
    {
		dump(stdout,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
        /* Free the device list */
		pcap_freealldevs(alldevs);
		return ;
	}
	else
	{
    	dump(stdout," Open device %s sucess",d->name);
    }
  int linktype = pcap_datalink(g_adhandle);
  switch(linktype)
  {
  case  DLT_EN10MB:
  //以太网（10Mb/100Mb/1000Mb/或者更高）；数据包以PPPoE头开始。
  dump(stdout,"DLT_EN10MB");
  break;
  case DLT_PPP_ETHER:
  dump(stdout,"DLT_PPP_ETHER");
  //RFC2516，PPPoE
  break;
  default:
  // 不支持的链路
  dump(stdout,"NOT SUPPORTED");
  return ;
  }
     struct bpf_program fcode;
     bpf_u_int32 NetMask=0xffffff;
	if (g_FilterString != "")
	{
		dump(stdout,"FilterString:%s",g_FilterString);
		// We should loop through the adapters returned by the pcap_findalldevs_ex()
		// in order to locate the correct one.
		//
		// Let's do things simpler: we suppose to be in a C class network ;-)
		NetMask=0xffffff;

		//compile the filter
		if(pcap_compile(g_adhandle, &fcode,g_FilterString, 1, NetMask) < 0)
		{
			pcap_close(g_adhandle);
			dump(stdout,"\nError compiling filter: wrong syntax.\nFilterStr:%s",g_FilterString);
			return;
		}

		//set the filter
		if(pcap_setfilter(g_adhandle, &fcode)<0)
		{
			pcap_close(g_adhandle);
			dump(stdout,"\nError setting the filter\n");
			return;
		}

	}
	/* At this point, we don't need any more the device list. Free it */
	pcap_freealldevs(alldevs);

	 /* start the capture */
	//g_thread->DoWatch() ;
}
void Tfrmmain::OnCatchPACKET(nodedata* node)
{
	mutex.lock();
	dump(stdout,"PackData:srcip: %s,dstip: %s",iptos(iptoul(node->srcip)),iptos(iptoul(node->dstip)));
	
	QStandardItemModel *model = (QStandardItemModel*)ui.lvw_root->model();
    QStandardItem* pitem=model->invisibleRootItem();
    int itemindex=g_sameRootPacksCount;
    QStandardItem *li;
    bool isfirstin = node->isroot;
    int count = node->packscount <=0? 1 : node->packscount;
	if(isfirstin)
	{
		g_sameRootPacksCount++;
		node->listitemindex = itemindex;
		dump(stdout,"newnode itemindex:%d",itemindex);
		li = new QStandardItem();
		li->setText(QString::number(itemindex));
		model->setItem(itemindex,0,li);
		model->setItem(itemindex,1,new QStandardItem(QString(node->starttime)));
		char srcipport[40];
		char dstipport[40];
		sprintf(srcipport,"%s:%d",iptos(iptoul(node->srcip)),node->sport);
		sprintf(dstipport,"%s:%d",iptos(iptoul(node->dstip)),node->dport);
		model->setItem(itemindex,2,new QStandardItem(srcipport));
		model->setItem(itemindex,3,new QStandardItem(dstipport));
		char proto_name[255];
		getprotoname(node->proto,proto_name);

		model->setItem(itemindex,4,new QStandardItem(QString(proto_name)));
		model->setItem(itemindex,5,new QStandardItem(QString::number(count)));
		QStandardItem* item = model->item(itemindex);
		g_ItemValues[item] = node;
		dump(stdout,"set treeview item(%d,%d) data:0x%08x",itemindex,0,node)
	}
	else
	{
		itemindex = node->listitemindex;
		//Q_ASSERT(itemindex>=0);
		model->setItem(itemindex,5,new QStandardItem(QString::number(count)));
    }
	mutex.unlock();

}
